package providers

import (
	"bufio"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"

	"github.com/rs/zerolog/log"
	"techoiceness.com/aiagent/llm-gateway/internal/llm/types"
)

// DeepSeekOptions DeepSeek 配置选项
type DeepSeekOptions struct {
	RequestTimeout time.Duration
	StreamTimeout  time.Duration
	StreamBufSize  int
	StreamChanSize int
	ScannerBufSize int
}

// DefaultDeepSeekOptions 默认配置
func DefaultDeepSeekOptions() *DeepSeekOptions {
	return &DeepSeekOptions{
		RequestTimeout: 3 * time.Minute,
		StreamTimeout:  10 * time.Minute,
		StreamBufSize:  4096,
		StreamChanSize: 100,
		ScannerBufSize: 4096,
	}
}

// DeepSeek DeepSeek 实现
type DeepSeek struct {
	apiURL           string
	apiKey           string
	httpClient       *http.Client
	streamHttpClient *http.Client
	options          *DeepSeekOptions
}

// NewDeepSeek 新建 DeepSeek 实例
func NewDeepSeek(apiURL, apiKey string) *DeepSeek {
	return NewDeepSeekWithOptions(apiURL, apiKey, DefaultDeepSeekOptions())
}

// NewDeepSeekWithOptions 使用自定义配置创建 DeepSeek 实例
func NewDeepSeekWithOptions(apiURL, apiKey string, options *DeepSeekOptions) *DeepSeek {
	httpClient := &http.Client{
		Timeout: options.RequestTimeout,
	}

	streamHttpClient := &http.Client{
		Timeout: options.StreamTimeout,
	}

	return &DeepSeek{
		apiURL:           apiURL,
		apiKey:           apiKey,
		httpClient:       httpClient,
		streamHttpClient: streamHttpClient,
		options:          options,
	}
}

// Chat 普通请求
func (d *DeepSeek) Chat(ctx context.Context, req types.Request) (*types.Response, error) {
	req.Stream = false // 确保不是流式请求

	// 读取请求体内容以保存原始数据
	reqBodyBytes, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}
	rawRequestBody := string(reqBodyBytes)
	reqBodyReader := bytes.NewReader(reqBodyBytes) // 创建 request body reader

	httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, d.apiURL, reqBodyReader)
	if err != nil {
		return nil, err
	}
	httpReq.Header.Set("Authorization", "Bearer "+d.apiKey)
	httpReq.Header.Set("Content-Type", "application/json")

	resp, err := d.httpClient.Do(httpReq)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 读取响应体并保存原始数据
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	rawResponseBody := string(body)

	if resp.StatusCode != http.StatusOK {
		log.Error().
			Str("provider", "deepseek").
			Int("status_code", resp.StatusCode).
			Str("response_body", rawResponseBody).
			Str("request_body", rawRequestBody).
			Str("content_type", resp.Header.Get("Content-Type")).
			Msg("DeepSeek Chat API error - full response details")

		// 尝试解析错误响应以获取更详细的错误信息
		var errorDetail string
		if rawResponseBody != "" {
			// 尝试解析JSON错误响应
			var apiError map[string]interface{}
			if err := json.Unmarshal([]byte(rawResponseBody), &apiError); err == nil {
				if errorBytes, err := json.MarshalIndent(apiError, "", "  "); err == nil {
					errorDetail = string(errorBytes)
				} else {
					errorDetail = rawResponseBody
				}
			} else {
				errorDetail = rawResponseBody
			}
		} else {
			errorDetail = "No response body"
		}

		return nil, fmt.Errorf("DeepSeek API error [%d %s]: %s", resp.StatusCode, resp.Status, errorDetail)
	}

	var respData types.Response
	if err := json.Unmarshal(body, &respData); err != nil {
		return nil, err
	}

	// 设置原始数据
	respData.RawRequestBody = rawRequestBody
	respData.RawResponseBody = rawResponseBody

	return &respData, nil
}

// ChatStream 流式请求
func (d *DeepSeek) ChatStream(ctx context.Context, req types.Request) (<-chan types.StreamResponse, error) {
	req.Stream = true                                            // 确保是流式请求
	req.StreamOptions = &types.StreamOptions{IncludeUsage: true} // 确保包含使用信息

	// 读取请求体内容以保存原始数据
	reqBodyBytes, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}

	rawRequestBody := string(reqBodyBytes)
	reqBodyReader := bytes.NewReader(reqBodyBytes) // 创建 request body reader

	httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, d.apiURL, reqBodyReader)
	if err != nil {
		return nil, err
	}

	// 设置 sse 请求头
	httpReq.Header.Set("Authorization", "Bearer "+d.apiKey)
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Accept", "text/event-stream")

	resp, err := d.streamHttpClient.Do(httpReq)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		// 读取错误响应体
		errorBody, err := io.ReadAll(resp.Body)
		resp.Body.Close()

		var errorBodyStr string
		if err != nil {
			errorBodyStr = fmt.Sprintf("Error reading response body: %v", err)
		} else {
			errorBodyStr = string(errorBody)
		}

		log.Error().
			Str("provider", "deepseek").
			Int("status_code", resp.StatusCode).
			Str("response_body", errorBodyStr).
			Str("request_body", rawRequestBody).
			Str("content_type", resp.Header.Get("Content-Type")).
			Str("content_length", resp.Header.Get("Content-Length")).
			Msg("DeepSeek ChatStream API error - full response details")

		// 尝试解析错误响应以获取更详细的错误信息
		var errorDetail string
		if errorBodyStr != "" {
			// 尝试解析JSON错误响应
			var apiError map[string]interface{}
			if err := json.Unmarshal([]byte(errorBodyStr), &apiError); err == nil {
				if errorBytes, err := json.MarshalIndent(apiError, "", "  "); err == nil {
					errorDetail = string(errorBytes)
				} else {
					errorDetail = errorBodyStr
				}
			} else {
				errorDetail = errorBodyStr
			}
		} else {
			errorDetail = "No response body"
		}

		return nil, fmt.Errorf("DeepSeek Stream API error [%d %s]: %s", resp.StatusCode, resp.Status, errorDetail)
	}

	streamChan := make(chan types.StreamResponse, d.options.StreamChanSize)

	go func() {
		defer resp.Body.Close()

		defer func() {
			if r := recover(); r != nil {
				streamChan <- types.StreamResponse{Error: fmt.Errorf("panic in stream processing: %v", r)}
			}
			close(streamChan)
		}()

		// 使用tee reader同时读取和保存原始响应数据
		var rawResponseBuf bytes.Buffer
		teeReader := io.TeeReader(resp.Body, &rawResponseBuf)

		scanner := bufio.NewScanner(teeReader)
		scanner.Buffer(nil, d.options.ScannerBufSize)

		for scanner.Scan() {
			// 检查上下文是否已取消
			select {
			case <-ctx.Done():
				streamChan <- types.StreamResponse{Error: ctx.Err()}
				return
			default:
			}

			line := scanner.Bytes()

			switch {
			case len(line) == 0:
				continue // 跳过空行
			case strings.HasPrefix(string(line), "data:"):
				data := bytes.TrimSpace(line[5:]) // 去掉 "data:" 前缀，然后去除前后空格
				if len(data) == 0 {
					continue // 跳过空数据行
				}

				if strings.TrimSpace(string(data)) == "[DONE]" {
					// 流结束，发送包含所有原始数据的最终响应
					finalResp := types.StreamResponse{
						RawRequestBody:  rawRequestBody,
						RawResponseBody: rawResponseBuf.String(), // 完整的原始SSE响应
					}
					streamChan <- finalResp
					return // 结束流处理
				}

				var streamResp types.StreamResponse
				if err := json.Unmarshal(data, &streamResp); err != nil {
					streamChan <- types.StreamResponse{Error: err}
					continue
				}

				streamChan <- streamResp
			case bytes.HasPrefix(line, []byte(":")):
				// 跳过注释行
				continue
			default:
				unexpectedErr := fmt.Errorf("unexpected line format: %s", string(line))
				streamChan <- types.StreamResponse{Error: unexpectedErr}
				return
			}
		}

		if err := scanner.Err(); err != nil {
			streamChan <- types.StreamResponse{Error: fmt.Errorf("scanner error: %v", err)}
			return
		}

		// 如果没有遇到[DONE]就结束了，也要发送原始数据
		finalResp := types.StreamResponse{
			RawRequestBody:  rawRequestBody,
			RawResponseBody: rawResponseBuf.String(),
		}
		streamChan <- finalResp
	}()

	return streamChan, nil
}
